/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
* Copyright (C) 2012 Sony Computer Entertainment Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "config.h"
#include "WebPageProxy.h"

#include "NativeWebKeyboardEvent.h"
#include "NotImplemented.h"
#include "PageClient.h"
#include "WebKitVersion.h"
#include "WebPageMessages.h"
#include "WebProcessProxy.h"

#include <manx/ImeEvent.h>
#include <manx/System.h>
#include <wtf/text/StringConcatenate.h>

using namespace WebCore;

namespace WebKit {

PlatformWidget WebPageProxy::viewWidget()
{
    return 0;
}

static String osVersionForUAString()
{
    return String(Manx::System::osName());
}

static String userVisibleWebKitVersionString()
{
    return String::format("%d.%d", WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION);
}

String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent)
{
    DEFINE_STATIC_LOCAL(String, osVersion, (osVersionForUAString()));
    DEFINE_STATIC_LOCAL(String, webKitVersion, (userVisibleWebKitVersionString()));

    return makeString("Mozilla/5.0 (", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko)", applicationNameForUserAgent.isEmpty() ? "" : " ", applicationNameForUserAgent);
}

void WebPageProxy::handleKeyboardEventManx(const NativeWebKeyboardEvent& event, int caretOffset)
{
    if (!isValid())
        return;

    m_keyEventQueue.append(event);

    process()->responsivenessTimer()->start();
    if (m_keyEventQueue.size() == 1) // Otherwise, sent from DidReceiveEvent message handler.
        process()->send(Messages::WebPage::KeyEventManx(event, caretOffset), m_pageID);
}

void WebPageProxy::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd)
{
    // FIXME: We need to find out how to proper handle the crashes case.
    if (!isValid())
        return;

    process()->send(Messages::WebPage::SetComposition(text, underlines, selectionStart, selectionEnd, replacementRangeStart, replacementRangeEnd), m_pageID);
}

void WebPageProxy::confirmComposition(const String& compositionString, int64_t selectionStart, int64_t selectionLength)
{
    if (!isValid())
        return;

    process()->send(Messages::WebPage::ConfirmComposition(compositionString, selectionStart, selectionLength), m_pageID);
}

void WebPageProxy::cancelComposition()
{
    if (!isValid())
        return;

    process()->send(Messages::WebPage::CancelComposition(), m_pageID);
}

void WebPageProxy::exitComposition()
{
    if (!isValid())
        return;

    if (m_keyEventQueue.isEmpty()) {
        process()->send(Messages::WebPage::ExitComposition(), m_pageID);
        return;
    }

    // Otherwise, sent from DidReceiveEvent message handler.
    m_pendingExitComposition = true;
}

void WebPageProxy::setValueToFocusedNode(const String& value)
{
    if (!isValid())
        return;

    process()->send(Messages::WebPage::SetValueToFocusedNode(value), m_pageID);
}

void WebPageProxy::clearSelectionWithoutBlur()
{
    if (!isValid())
        return;
    process()->send(Messages::WebPage::ClearSelectionWithoutBlur(), m_pageID);
}

void WebPageProxy::setCaretVisible(bool visible)
{
    if (!isValid())
        return;
    process()->send(Messages::WebPage::SetCaretVisible(visible), m_pageID);
}

void WebPageProxy::saveRecentSearches(const String&, const Vector<String>&)
{
    notImplemented();
}

void WebPageProxy::loadRecentSearches(const String&, Vector<String>&)
{
    notImplemented();
}

void WebPageProxy::editorStateChanged(const EditorState& editorState)
{
    Manx::Ime::EditorState::EventType eventType = Manx::Ime::EditorState::None;

    if ((m_editorState.isContentEditable != editorState.isContentEditable) && !editorState.shouldIgnoreCompositionSelectionChange)
        if (editorState.isContentEditable)
            eventType = Manx::Ime::EditorState::ShouldImeOpen;
        else
            eventType = Manx::Ime::EditorState::ShouldImeClose;
    else if (m_editorState.isContentEditable && editorState.isContentEditable && !editorState.shouldIgnoreCompositionSelectionChange
        && ((m_editorState.fieldLang != editorState.fieldLang)
        || (m_editorState.fieldRect != editorState.fieldRect)
        || (m_editorState.fieldType != editorState.fieldType)
        || (m_editorState.hasPreviousNode != editorState.hasPreviousNode)
        || (m_editorState.hasNextNode != editorState.hasNextNode)))
        eventType = Manx::Ime::EditorState::ShouldImeReopen;

    if (eventType != Manx::Ime::EditorState::None)
        m_pageClient->didChangeEditorState(eventType, editorState);

    if ((editorState.caretOffset != -1)
        && ((editorState.fieldText != m_editorState.fieldText) || (editorState.caretOffset != m_editorState.caretOffset)))
        m_pageClient->didChangeEditorState(Manx::Ime::EditorState::ShouldImeUpdateContext, editorState);

    if (!editorState.selectionIsRange && editorState.hasComposition)
        m_pageClient->didChangeCompositionState(editorState.compositionRect);

    if (editorState.selectionIsRange && !editorState.shouldIgnoreCompositionSelectionChange)
        m_pageClient->didChangeSelectionState(editorState.selectedText, editorState.selectedRect);
    else if (m_editorState.selectionIsRange && !m_editorState.shouldIgnoreCompositionSelectionChange && !editorState.selectionIsRange)
        m_pageClient->didChangeSelectionState("", WebCore::IntRect());

    m_editorState = editorState;
}

} // namespace WebKit
